package com.yycx.starter.thirdlogin.controller;


import com.alibaba.fastjson.JSONObject;
import com.yycx.common.base.service.BaseThirdLoginService;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.configuration.OpenCommonProperties;
import com.yycx.common.constants.AuthConstants;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.security.http.OpenRestTemplate;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.utils.DateUtils;
import com.yycx.common.utils.RedisUtils;
import com.yycx.starter.thirdlogin.constants.ThirdLoginConstants;
import com.yycx.starter.thirdlogin.service.GiteeAuthServiceImpl;
import com.yycx.starter.thirdlogin.service.QQAuthServiceImpl;
import com.yycx.starter.thirdlogin.service.WechatAuthServiceImpl;
import com.yycx.starter.thirdlogin.utils.MD5Utils;
import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Map;

/**
 * @author: 三方登录回调
 * @date: 2018/11/9 15:43
 */
@Api(tags = "三方登录回调")
@Controller
@AllArgsConstructor
public class ThirdLoginCallBackController {

    private final QQAuthServiceImpl qqAuthService;

    private final WechatAuthServiceImpl wechatAuthService;

    private final GiteeAuthServiceImpl giteeAuthService;

    private final OpenRestTemplate openRestTemplate;

    private final OpenCommonProperties openCommonProperties;

    private final RedisUtils redisUtils;


    private final Map<String, BaseThirdLoginService> thirdLoginServiceMap;


    /**
     * QQ第三方登录回调
     *
     * @param code code
     * @param type type
     * @return
     */
    @GetMapping("/oauth/qq/callback")
    public String oauthByQQ(@RequestParam(value = "code") String code, @RequestParam(value = "type") String type, @RequestHeader HttpHeaders headers) {
        JSONObject jsonObject = wechatAuthService.getAccessToken(code);
        String token = "";
        if (jsonObject != null) {
            String accessToken = jsonObject.getString("access_token");
            String openId = qqAuthService.getOpenId(accessToken);
            if (openId != null) {
                if (FlymeUtils.isNotEmpty(thirdLoginServiceMap)) {
                    thirdLoginServiceMap.get(type + "AccountServiceImpl").register(openId, openId, AuthConstants.LOGIN_QQ, "");
                    token = getToken(openId, openId, "", "", AuthConstants.LOGIN_QQ, "", headers);
                } else {
                    ApiAssert.failure("thirdLoginService未找到实现类");
                }
            }
        }
        return "redirect:" + qqAuthService.getLoginSuccessUrl() + "?access_token=" + "Bearer " + token;
    }

    /**
     * 微信第三方登录回调
     *
     * @param code
     * @param type
     * @return
     */
    @GetMapping("/oauth/wechat/callback")
    public String oauthByWechat(@RequestParam(value = "code") String code, @RequestParam(value = "type") String type, @RequestHeader HttpHeaders headers) {
        JSONObject jsonObject = wechatAuthService.getAccessToken(code);
        String token = "";
        if (jsonObject != null) {
            String accessToken = jsonObject.getString("access_token");
            String openid = jsonObject.getString("openid");
            JSONObject userInfo = wechatAuthService.getUserInfo(accessToken, openid);
            if (userInfo != null) {
                if (FlymeUtils.isNotEmpty(thirdLoginServiceMap)) {
                    String unionid = userInfo.getString("unionid");
                    String nickname = userInfo.getString("nickname");
                    String headimgurl = userInfo.getString("headimgurl");
                    //thirdLoginServiceMap.get(type+"AccountServiceImpl").register(nickname, headimgurl, AuthConstants.LOGIN_WECHAT, nickname);
                    token = getToken(unionid, unionid, nickname, headimgurl, AuthConstants.LOGIN_WECHAT, "USER", headers);
                } else {
                    ApiAssert.failure("thirdLoginService未找到实现类");
                }
            }
        }
        return "redirect:" + wechatAuthService.getLoginSuccessUrl() + "?access_token=" + "Bearer " + token;
    }


    /**
     * 码云第三方登录回调
     *
     * @param code
     * @param type
     * @return
     */
    @GetMapping("/oauth/gitee/callback")
    public String oauthByGitee(@RequestParam(value = "code") String code, @RequestParam(value = "type") String type, @RequestHeader HttpHeaders headers) {
        JSONObject jsonObject = wechatAuthService.getAccessToken(code);
        String token = "";
        if (jsonObject != null) {
            String accessToken = jsonObject.getString("access_token");
            JSONObject userInfo = giteeAuthService.getUserInfo(accessToken, null);
            if (FlymeUtils.isNotEmpty(userInfo)) {
                String openId = userInfo.getString("id");
                String name = userInfo.getString("name");
                if (openId != null) {
                    if (FlymeUtils.isNotEmpty(thirdLoginServiceMap)) {
                        //  thirdLoginServiceMap.get(type+"AccountServiceImpl").register(openId, openId, AuthConstants.LOGIN_GITEE, name);
                        token = getToken(openId, openId, "", "", AuthConstants.LOGIN_GITEE, "", headers);
                    } else {
                        ApiAssert.failure("thirdLoginService未找到实现类");
                    }
                }
            }

        }
        return "redirect:" + giteeAuthService.getLoginSuccessUrl() + "?access_token=" + "Bearer " + token;
    }


    /**
     * 单点登录回调
     *
     * @param account
     * @return
     */
    @GetMapping("/oauth/custom/callback")
    @ResponseBody
    public ResultBody oauthByCustom(@RequestParam(value = "account") String account, @RequestParam(value = "tempCode") String tempCode, @RequestParam(value = "sign") String sign, @RequestHeader HttpHeaders headers) {
        if (FlymeUtils.isEmpty(sign)) {
            return ResultBody.failed("缺少签名");
        }
        String defaultPassword = ThirdLoginConstants.USER_ACCOUNT_TYPE_OTHER_PASSWORD;
        String nowDate = DateUtils.formatDate();
        String againSign = MD5Utils.MD5(account + defaultPassword + nowDate + tempCode).toUpperCase();
        if (!againSign.equals(sign)) {
            return ResultBody.failed("签名不正确");
        }
        boolean hasKey = redisUtils.hasKey(account);
        if (!hasKey) {
            return ResultBody.failed("临时code已失效,请重新获得");
        }
        String redisCode = redisUtils.getString(account);
        if (!redisCode.equals(tempCode)) {
            return ResultBody.failed("临时code不存在,请重新获得");
        }

        String token = "";
        if (FlymeUtils.isNotEmpty(account)) {
            token = getToken(account, ThirdLoginConstants.USER_ACCOUNT_TYPE_OTHER_PASSWORD, "", "", ThirdLoginConstants.USER_ACCOUNT_TYPE_OTHER, "USER", headers);
        }
        return ResultBody.ok(token);
    }


    /**
     * 第三方登录获取token
     *
     * @param userName
     * @param password
     * @param accountType
     * @param headers
     * @return
     */
    private String getToken(String userName, String password, String nickName, String avatar, String accountType, String userType, HttpHeaders headers) {
        // 使用oauth2密码模式登录.
        MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("username", userName);
        postParameters.add("password", password);
        postParameters.add("accountType", accountType);
        postParameters.add("client_id", openCommonProperties.getClientId());
        postParameters.add("accountType", accountType);
        postParameters.add("avatar", avatar);
        postParameters.add("nickName", nickName);
        postParameters.add("userType", FlymeUtils.getString(userType, "USER"));
        postParameters.add("client_secret", openCommonProperties.getClientSecret());
        postParameters.add("grant_type", "password");
        // 添加请求头区分,第三方登录
        headers.add(AuthConstants.HEADER_X_THIRDPARTY_LOGIN, accountType);
        // 使用客户端的请求头,发起请求
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        // 强制移除 原来的请求头,防止token失效
        headers.remove(HttpHeaders.AUTHORIZATION);
        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(postParameters, headers);
        JSONObject result = openRestTemplate.postForObject(openCommonProperties.getAccessTokenUri(), request, JSONObject.class);
        if (result.containsKey("data")) {
            JSONObject data = result.getJSONObject("data");
            if (data.containsKey("access_token")) {
                return data.getString("access_token");
            }
        }
        return null;
    }


}
